export default class Promise {
	constructor(executor) {
		this.PromiseState = 'pending';
		this.PromiseResult = null;
		// 这个属性用来保存回调
		this.callbacks = [];

		let resolve = (data) => {
			// 改变状态
			if (this.PromiseState !== 'pending') return;
			this.PromiseState = 'fulfilled';
			this.PromiseResult = data;
			// 如果异步任务执行时
			setTimeout(() => {
				this.callbacks.forEach(callback => {
					if (callback.onResolved) {
						callback.onResolved(data);
					}
				})
			});
		}

		let reject = (data) => {
			if (this.PromiseState !== 'pending') return;
			this.PromiseState = 'rejected';
			this.PromiseResult = data;
			setTimeout(() => {
				this.callbacks.forEach(callback => {
					if (callback.onRejected) {
						callback.onRejected(data);
					}
				})
			});
		}

		try {
			// 立即调用执行器函数'
			executor(resolve, reject);
		} catch (e) {
			reject(e);
		}
	}

	then(onResolved, onRejected) {
		if (typeof onResolved !== "function") {
			onResolved = value => value;
		}
		if (typeof onRejected !== "function") {
			onRejected = reason => {
				throw reason;
			}
		}
		// 调用回调函数
		return new Promise((resolve, reject) => {
			let callback = (resolved) => {
				try {
					let result = resolved(this.PromiseResult);
					if (result instanceof Promise) {
						result.then(value => {
							resolve(value);
						}, reason => {
							reject(reason);
						})
					} else {
						resolve(result);
					}
				} catch (e) {
					reject(e);
				}
			}
			if (this.PromiseState === 'fulfilled') {
				setTimeout(() => {
					callback(onResolved)
				});

			}
			if (this.PromiseState === 'rejected') {
				setTimeout(() => {
					callback(onRejected)
				});
			}
			// 异步任务,需要在此保存回调函数
			if (this.PromiseState === 'pending') {
				this.callbacks.push({
					onResolved: () => {
						callback(onResolved);
					},
					onRejected: () => {
						callback(onRejected);
					}
				})
			}
		})
	}

	catch(onRejected) {
		return this.then(undefined, onRejected);
	}

	static resolve(value) {
		return new Promise((resolve, reject) => {
			if (value instanceof Promise) {
				value.then(v => {
					resolve(v);
				}, r => {
					reject(r);
				})
			} else {
				resolve(value);
			}
		});
	}

	static reject(value) {
		return new Promise((resolve, reject) => {
			reject(value);
		});
	}

	static all(promises) {
		return new Promise((resolve, reject) => {
			let count = 0;
			let arr = [];
			for (let i = 0; i < promises.length; i++) {
				promises[i].then(v => {
					count++;
					arr[i] = v;
					if (count === promises.length) {
						resolve(arr);
					}
				}, r => {
					reject(r);
				})
			}
		})
	}

	static race(promises) {
		return new Promise((resolve, reject) => {
			for (let i = 0; i < promises.length; i++) {
				promises[i].then(v => {
					resolve(v);
				}, r => {
					reject(r);
				})
			}
		})
	}
}
